package wiki.kaizen.cloud.shiro.stateless.util;

import lombok.Setter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * redis 缓存工具类
 * @author  xeepoo
 * */
public class RedisUtil {


    @Setter
    private static RedisTemplate<String,Object> redisTemplate;

    private final static Map<String,Cache> caches;
    static {
        caches = new HashMap<>();
    }

    public static  <T> Cache<T> getCache(String prefix){
        if (caches.containsKey(prefix)){
            return (Cache<T>)caches.get(prefix);
        }else{
            Cache<T> cache = new Cache<>(prefix);
            caches.put(prefix,cache);
            return cache;
        }

    }

    public static class Cache<T>{
        private final String prefix;
        private Cache(String prefix){
            this.prefix = prefix;
        }

        /**
         * 获取set是设置的过期时间 减去剩余过期时间得到的秒数
         * @param key
         * @param totalSenconds
         * @return
         */
        public Long passSeconds(String key,Long totalSenconds){
            key = prefix+key;
            Object value = this.get(key);
            if (value == null){
                return null;
            }
            Long expire = this.getExpire(key);
            if (expire<=0){
                return null;
            }
            return totalSenconds - expire;
        }

        /**
         * 指定缓存失效时间
         *
         * @param key  键
         * @param time 时间(秒)
         */
        private void expire(String key, long time) {
            key = prefix+key;
            if (time > 0) {
                try {
                    redisTemplate.expire(key, time, TimeUnit.MILLISECONDS);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        /**
         *清除库内容
         * */
        public void clearAll(){
            redisTemplate.getConnectionFactory().getConnection().flushDb();
        }

        /**
         * 获取库长度
         * */
        public Long size(){
            return redisTemplate.getConnectionFactory().getConnection().dbSize();
        }

        /**
         *获取所有key
         * */
        public Set<String> keys(String pref){
            String key = prefix +( pref==null?"":pref);
            return  redisTemplate.keys(key + "*");
        }

        /**
         * 根据key 获取过期时间
         *
         * @param key 键 不能为null
         * @return 时间(秒) 返回0代表为永久有效
         */
        public Long getExpire(String key) {
            key = prefix+key;
            return redisTemplate.getExpire(key, TimeUnit.MILLISECONDS);
        }

        /**
         * 判断key是否存在
         *
         * @param key 键
         * @return true 存在 false不存在
         */
        public boolean hasKey(String key) {
            key = prefix+key;
            try {
                return redisTemplate.hasKey(key);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

        /**
         * 删除缓存
         *
         * @param key 可以传一个值 或多个
         */
        public void del(String... key) {
            String[] keys = new String[key.length];
            for (int i = 0; i < key.length; i++) {
                keys[i] = prefix + key[i];
            }
            if (key.length > 0) {
                if (key.length == 1) {
                    redisTemplate.delete(keys[0]);
                } else {
                    redisTemplate.delete(CollectionUtils.arrayToList(keys));
                }
            }
        }

        //============================String=============================

        /**
         * 普通缓存获取
         *
         * @param key 键
         * @return 值
         */
        public T get(String key) {
            return key == null ? null : (T) redisTemplate.opsForValue().get(prefix+key);
        }

        /**
         * 普通缓存放入
         *
         * @param key   键
         * @param value 值
         * @return true成功 false失败
         */
        public boolean set(String key, T value) {
            key = prefix+key;
            try {
                redisTemplate.opsForValue().set(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }

        }

        /**
         * 普通缓存放入并设置时间
         *
         * @param key   键
         * @param value 值
         * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
         * @return true成功 false 失败
         */
        public boolean set(String key, T value, long time) {
            key = prefix+key;
            try {
                if (time > 0) {
                    redisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS);
                } else {
                    set(key, value);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

    }

}
